/**
 * @file ec.h
 * @brief 定义椭圆曲线公共运算
 * @author lemene
 * @license BSD
 */

#ifndef SM_EC_H
#define SM_EC_H

#include "uinteger.h"

#ifdef __cplusplus
extern "C" {
#endif


/**
 * 定义曲线上的点，其中z=0用于区分无穷远点
 */
typedef struct ECPoint_st {
	UInteger x;
	UInteger y;
	uint32_t z;
} ECPoint;

/**
 * 通过曲线点设置曲线点
 * @param [out] a 被设置的曲线点
 * @param [in] b 需要设置的至
 * @return a的指针
 * @see ECPoint_FromUInt
 */
const ECPoint* ECPoint_From(ECPoint *a, const ECPoint *b);


/** 
 * 通过整数设置曲线点的值
 * @param [out] a 被设置值的曲线点
 * @param [in] x, y, z 需要设置的值
 * @return a的指针
 * @see ECPoint_From
 */
const ECPoint* ECPoint_FromUInt(ECPoint *a, const UInteger *x, const UInteger *y, uint32_t z);

/**
 * 判断两个曲线点是否相同
 * @param [in] a,b 被比较的值
 * @return true表示相同，false表示不同
 */
bool ECPoint_Equal(const ECPoint *a, const ECPoint *b);



/**
 * 执行c = a + b的运算
 * @param [in] ec
 * @param [in] a,b
 * @param [out] c
 */

/**
 * 执行b = k*a的运算
 * @param [in] ec
 * @param [in] a,k
 * @param [out] b
 */



/** 判断点是否属于曲线 */

typedef struct ECWork_st ECWork;
typedef void (*EC_AddFcn)(const ECWork* ec, const ECPoint *a, const ECPoint *b, ECPoint *c);
typedef void (*EC_MulFcn)(const ECWork* ec, const UInteger *k, const ECPoint *a, ECPoint *b);
typedef void (*EC_OnFcn)(const ECWork* ec, const ECPoint *a);
typedef size_t (*EC_ZAFcn)(const ECWork *ec, uint8_t* za, size_t zasize);

#define ECWork_HEAD 	\
	EC_AddFcn add;		\
	EC_MulFcn mul;		\
	EC_OnFcn  on;		\
	EC_ZAFcn  za;		\
	size_t size;		\

typedef struct ECWork_st {
	ECWork_HEAD;
} ECWork; 

#define EC_ADD(ec, a, b, c) (ec)->add((ECWork*)(ec), a, b, c)
#define EC_MUL(ec, k, a, b) (ec)->mul((ECWork*)(ec), k, a, b)
#define EC_ON(ec, a) (ec)->on((ECWork*)(ec), a)
#define EC_SIZE(ec) (((ec)->size+7)/8)

void EC_Mul(const ECWork *ec, const UInteger *k, const ECPoint *a, ECPoint *b);

#ifdef __cplusplus
}	// extern "C" {
#endif

#endif // SM_EC_H

